package com.lanxum.common.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import com.lanxum.common.utils.CommonUtil;
import com.lanxum.common.utils.FileUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.*;

/**
 * @author li.sun
 * @Description:
 * @date 2020/10/14 16:00
 */
public class AsyncPdfTaskService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncPdfTaskService.class);

//    private static PdfReader reader;

    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(100, 500, 100L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(2000));

    public Future submit(String pdfData, String outPdfFilePath, Integer copiesNumber) {
        return threadPoolExecutor.submit(new SyncDataThread(pdfData, outPdfFilePath, copiesNumber));
    }


    public class SyncDataThread implements Callable {

        private JSONObject jsonObject = new JSONObject();

        public SyncDataThread(String pdfData, String outPdfFilePath, Integer copiesNumber) {

            JSONObject rootJson = JSON.parseObject(pdfData);
            String fileName = rootJson.getString("fileName");

            JSONObject pdfDataJson = rootJson.getJSONObject("pdfData");
            String filePath = pdfDataJson.getString("filePath");
            String inputPdfFilePath = filePath + File.separator + fileName;

            if (new File(inputPdfFilePath).exists()) {
                String outPdfFilePathCopies = pdfDrawImage(pdfData, outPdfFilePath, copiesNumber);
                jsonObject.put("outPdfFilePathCopies", outPdfFilePathCopies);
            }
        }

        /**
         * 将PDF文件中嵌入条码图片
         */
        public String pdfDrawImage(String pdfData, String outPdfFilePath, Integer copiesIndex) {
            String outPdfFilePathCopiesTemp = null;
            String outPdfFilePathCopies = null;
            String newfile = null;
            PdfReader reader = null;
            PdfStamper stamper = null;
            FileOutputStream fileOutputStream = null;
            try {
                JSONObject rootJson = JSON.parseObject(pdfData);
                String fileName = rootJson.getString("fileName");
                String fileNameSub = fileName.substring(0, fileName.lastIndexOf("."));
                String copies = rootJson.getString("copies");
                String pages = rootJson.getString("pages");

                JSONObject pdfDataJson = rootJson.getJSONObject("pdfData");
                String filePath = pdfDataJson.getString("filePath");
                String duplex = pdfDataJson.getString("duplex");
                String paperSize = pdfDataJson.getString("paperSize");

                String imagePosition = pdfDataJson.getString("imagePosition");
                if (StringUtils.isBlank(imagePosition))
                    imagePosition = "bottom-right";
                String shiftAdjustmentX = pdfDataJson.getString("shiftAdjustmentX");
                if (StringUtils.isBlank(shiftAdjustmentX))
                    shiftAdjustmentX = "0";
                String shiftAdjustmentY = pdfDataJson.getString("shiftAdjustmentY");
                if (StringUtils.isBlank(shiftAdjustmentY))
                    shiftAdjustmentY = "0";
                String orientation = pdfDataJson.getString("orientation");
                if (StringUtils.isBlank(orientation))
                    orientation = "0";
                String width = pdfDataJson.getString("width");
                if (StringUtils.isBlank(width))
                    width = "150";
                String height = pdfDataJson.getString("height");
                if (StringUtils.isBlank(height))
                    height = "30";
                String systemType = pdfDataJson.getString("systemType");
                if (StringUtils.isBlank(systemType))
                    systemType = "Liunx";
                String inputPdfFilePath = filePath + File.separator + fileName;


                JSONObject barcodeDataJson = rootJson.getJSONObject("barcodeData");
                String outBarcodePngPath = barcodeDataJson.getString("outBarcodePngPath");


                String copiesNumber = CommonUtil.handleCopiesPages(copies, copiesIndex);
                //一份嵌条码pdf文件路径
                outPdfFilePathCopiesTemp = outPdfFilePath + File.separator + fileNameSub + copiesNumber + ".pdf";

                // 创建一个pdf读入流
                reader = new PdfReader(inputPdfFilePath);
                // 根据一个pdfreader创建一个pdfStamper.用来生成新的pdf.
                fileOutputStream = new FileOutputStream(outPdfFilePathCopiesTemp);
                stamper = new PdfStamper(reader, fileOutputStream);
                Integer numberPages = reader.getNumberOfPages();

//			 双面打印时，判断页数是否为奇数，false-偶数，true-奇数,如果是奇数在PDF末尾添加一个空白页;duplex-0：单面（默认），1：双面
//                if (Integer.parseInt(copies) > 1 && StringUtils.equals(duplex, "1") && numberPages % 2 != 0) {
//                    stamper.insertPage(numberPages + 1, reader.getPageSizeWithRotation(1));
//                }
                logger.info("将PDF文件中嵌入条码图片,reader.getNumberOfPages：{}", numberPages);
                for (int i = 1; i <= numberPages; i++) {

                    // 获得pdfstamper在当前页的上层打印内容.也就是说 这些内容会覆盖在原先的pdf内容之上.
                    PdfContentByte over = stamper.getOverContent(i);
                    // 当前页的下层打印内容 按自己需求选择
                    // over = stamper.getUnderContent(i);

                    // 用pdfreader获得当前页字典对象.包含了该页的一些数据.比如该页的坐标轴信息.
                    PdfDictionary p = reader.getPageN(i);

                    // 拿到mediaBox 里面放着该页pdf的大小信息.
                    PdfObject po = p.get(new PdfName("MediaBox"));
                    // po是一个数组对象.里面包含了该页pdf的坐标轴范围.
                    PdfArray pa = (PdfArray) po;

                    // 创建一个image对象.
                    String pagesNumber = CommonUtil.handleCopiesPages(numberPages.toString(), i);
                    String barcodeImgFilePath = outBarcodePngPath + File.separator + fileName + "_" + copiesNumber + "_" + pagesNumber + ".png";
                    logger.debug("将PDF文件中嵌入条码图片,barcodeImgFilePath：{}", barcodeImgFilePath);
                    Image image = Image.getInstance(barcodeImgFilePath);
                    PdfNumber pnHeight = (PdfNumber) pa.getArrayList().get(2);
                    PdfNumber pnWidth = (PdfNumber) pa.getArrayList().get(3);
                    float pageWidth = (float) pnWidth.doubleValue();
                    float pageHeight = (float) pnHeight.doubleValue();
                    logger.info("---------------------纸张方向:{};纸张高度:{};纸张宽度:{}", orientation,pageHeight,pageWidth);
                    logger.info("---------------------shiftAdjustmentX:{};shiftAdjustmentY:{};", shiftAdjustmentX,shiftAdjustmentY);
                    // 设置image对象的输出位置pa.getAsNumber(pa.size()-1).floatValue() 是该页pdf坐标轴的y轴的最大值 0, 0,
                    // 841.92, 595.32

                    // 厘米像素转换
                    // 300dpi 1厘米=118.11像素; 600dpi 1厘米=236.22像素
                    // image.setAbsolutePosition(xpos - 2.2f*236.22f, 0.5f*118.11f);

//                    float pos = pageWidth;

                    // 默认右下
                    float absoluteXpos = pageWidth - Float.valueOf(width) + Float.valueOf(shiftAdjustmentX);
                    float absoluteYpos = Float.valueOf(height)+Float.valueOf(shiftAdjustmentY);

                    float middleNumber = 0;
                    if (StringUtils.equals(orientation, "1")) {// 横向
                        middleNumber = pageWidth;
                        pageWidth = pageHeight;
                        pageHeight = middleNumber;
                        // 由于windows/liunx位置不一致，所以进行区。windows横向条码位置正确，Liunx横向条码位置错误
                        if (StringUtils.equalsIgnoreCase(systemType, "windows")) {
                            // windows
                            if (StringUtils.equals(paperSize, "A3"))
                                absoluteXpos = pageWidth - Float.valueOf(width);
                            else
                                absoluteXpos = pageWidth - Float.valueOf(width) + Float.valueOf(shiftAdjustmentX);
                        } else {
                            // liunx
                            if (StringUtils.equals(paperSize, "A3"))
                                absoluteXpos = pageWidth - Float.valueOf(width) + 310F;
                            else
                                absoluteXpos = pageWidth - Float.valueOf(width) + Float.valueOf(shiftAdjustmentX) + 200F;
                        }
                    }


                    logger.info("---------------------条码位置:{};", imagePosition);
                    switch (imagePosition) {
                        case "bottom-left":
                            // 底部左下
                            absoluteXpos = Float.valueOf(shiftAdjustmentX);
                            break;
                        case "bottom":
                            // 底部居中
                            absoluteXpos = (pageWidth - Float.valueOf(width) + Float.valueOf(shiftAdjustmentX)) / 2;
                            break;
                        case "top":
                            // 顶部居中
                            absoluteXpos = (pageWidth - Float.valueOf(width) + Float.valueOf(shiftAdjustmentX)) / 2;
                            absoluteYpos = pageHeight - Integer.parseInt(height);
                            break;
                        case "top-left":
                            // 顶部左上
                            absoluteXpos = Float.valueOf(shiftAdjustmentX);
                            absoluteYpos = pageHeight - Integer.parseInt(height);
                            break;
                        case "top-right":
                            // 顶部右上
                            absoluteYpos = pageHeight - Integer.parseInt(height);;
                            break;
                        default:
                            break;
                    }

                    logger.info("将PDF文件中嵌入条码图片,paperSize：{},absoluteXpos：{},absoluteYpos：{},shiftAdjustmentX：{}, shiftAdjustmentY:{}, pageWidth:{}, width:{}", paperSize, absoluteXpos, absoluteYpos, shiftAdjustmentX, shiftAdjustmentY, pageWidth, width);
                    logger.info("---------------------absoluteXpos:{};absoluteYpos:{};", absoluteXpos,absoluteYpos);
                    image.setAbsolutePosition(absoluteXpos, absoluteYpos);
                    // 设置插入的图片大小
                    image.scaleToFit(Float.valueOf(width), Float.valueOf(height));
                    over.addImage(image);
                }
                stamper.close();
                fileOutputStream.close();

                //			 双面打印时，判断页数是否为奇数，false-偶数，true-奇数,如果是奇数在PDF末尾添加一个空白页
                if (Integer.parseInt(copies) > 1 && StringUtils.equals(duplex, "1") && numberPages % 2 != 0) {
                    ClassPathResource classPathResource = new ClassPathResource("templates/blankPage.pdf");
                    InputStream inputStream = classPathResource.getInputStream();
                    File blankFile = new File("/opt/DYSJ/printJava/puf/zyj/blankPage.pdf");
                    if (!blankFile.exists())
                        FileUtils.copyInputStreamToFile(inputStream, blankFile);

                    String[] files = {outPdfFilePathCopiesTemp, blankFile.getAbsolutePath()};
                    Long sysLong = System.currentTimeMillis();
                    newfile = outPdfFilePathCopiesTemp + sysLong + ".pdf";

                    FileUtil.mergePdfFiles(files, newfile);


                    reader = new PdfReader(newfile);
                    outPdfFilePathCopies = outPdfFilePath + File.separator + fileNameSub + "_" + copiesNumber + ".pdf";
                    FileUtil.splitPDFFile(newfile, outPdfFilePathCopies, 1, reader.getNumberOfPages());
                }

            } catch (Exception e) {
                logger.error("将PDF文件中嵌入条码图片,Exception:{}", e);
            } finally {
                reader.close();
//                if (StringUtils.isNotBlank(outPdfFilePathCopiesTemp)) {
//                    File outFile = new File(outPdfFilePathCopiesTemp);
//                    if (outFile.exists()) {
//                        outFile.delete();
//                    }
//                }
                if (StringUtils.isNotBlank(newfile)) {
                    File newfileFile = new File(newfile);
                    if (newfileFile.exists())
                        newfileFile.delete();
                }
            }
            if (StringUtils.isNotBlank(outPdfFilePathCopies))
                return outPdfFilePathCopies;
            else
                return outPdfFilePathCopiesTemp;
        }

        @Override
        public Object call() throws Exception {
            return jsonObject;
        }
    }
}
